package TextNor.Read;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import DecisionTree.AttributeSet;
import DecisionTree.AttributeValue;
import DecisionTree.DecisionTree;
import DecisionTree.IdSymbolicAttribute;
import DecisionTree.Item;
import DecisionTree.ItemSet;
import DecisionTree.KnownSymbolicValue;
import DecisionTree.UnknownSymbolicValue;
import DecisionTree.io.ItemSetReader;
import DecisionTree.io.ReadWriteDecisionTree;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

/**
 *
 * @author phamthanh
 */
public final class ReadNgangCheo {

    private ArrayList tokenAr = new ArrayList();
    private ArrayList itemAr = new ArrayList();
    private AttributeSet attributeSet;
    private DecisionTree tree;
    private ItemSet learningSet;
    private ArrayList greekAr = new ArrayList();
    private ArrayList wordAr = new ArrayList();


//    public static void main(String argv[]) throws XMLStreamException, IOException {
//        NumTag nt = new NumTag();
//
//
//    }
    public ReadNgangCheo(String inf, String ouf) throws FileNotFoundException, XMLStreamException, IOException, ClassNotFoundException {

        System.out.println("package TextNor.Read; class ReadNgangCheo");

        long startTime = System.currentTimeMillis();
        setTokenAr(inf);
        setGreek();
        setItemAr();
        
        System.out.println("package TextNor.Read; Class REadNgangCheo; method ReadNgangCheo");
        createDecisionTree();
        asignFullValue(inf, ouf);
        long endTime = System.currentTimeMillis();
        long time = endTime - startTime;
        System.out.println("Thoi gian gan the num la: " + time);
    }

    public void createDecisionTree() throws IOException, FileNotFoundException, ClassNotFoundException {
        this.learningSet = null;
        try {
            //learningSet = ItemSetReader.read(new FileReader("data\\dt\\tree.db"));
            learningSet = ItemSetReader.read("data\\tree\\ngangcheotreedata.db");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("khong doc duoc file");
        }

        this.attributeSet = learningSet.attributeSet();

//        Vector testAttributesVector = new Vector();
//
//        testAttributesVector.add(attributeSet.findByName("tknBf2"));
//        testAttributesVector.add(attributeSet.findByName("tknBf1"));
//        testAttributesVector.add(attributeSet.findByName("nswStr"));
//        testAttributesVector.add(attributeSet.findByName("tknAf1"));
//        testAttributesVector.add(attributeSet.findByName("tknAf2"));
//
//
//        AttributeSet testAttributes = new AttributeSet(testAttributesVector);
//        SymbolicAttribute goalAttribute =
//                (SymbolicAttribute) learningSet.attributeSet().findByName("classNsw");
//
//        this.tree = buildTree(learningSet, testAttributes,
//                goalAttribute);
               ReadWriteDecisionTree rwd=new ReadWriteDecisionTree();
//        rwd.writeToFile("data//dt//numTree.db", tree);
        tree=rwd.readFromFile("data//tree//ngangcheotree.db");

    }

//    static private DecisionTree buildTree(ItemSet learningSet,
//            AttributeSet testAttributes,
//            SymbolicAttribute goalAttribute) {
//        DecisionTreeBuilder builder = new DecisionTreeBuilder(learningSet, testAttributes, goalAttribute);
//
//        return builder.build().decisionTree();
//    }

    public String guessFull(int itemIndex) {
        ALPHA num = (ALPHA) itemAr.get(itemIndex);
        Item item = convertNumToItem(num);
//        Item item=learningSet.item(0);
        KnownSymbolicValue guessedGoalAttributeValue = tree.guessGoalAttribute(item);
        System.out.println(tree.getGoalAttribute().valueToString(guessedGoalAttributeValue));
        return tree.getGoalAttribute().valueToString(guessedGoalAttributeValue);
////        return "";
    }

    public Item convertNumToItem(ALPHA num) {
//        AttributeValue[] values = new AttributeValue[8];
//
//        values[1] = new KnownNumericalValue(num.getChaCount());
//        values[2] = new KnownNumericalValue(num.getNumCount());
//        IdSymbolicAttribute attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(3);
//        values[3] = new KnownSymbolicValue(attribute.find(num.gettknBf2()));
//
//        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(4);
//        values[4] = new KnownSymbolicValue(attribute.find(num.gettknBf1()));
//
////        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(5);
////        values[5] = new KnownSymbolicValue(attribute.find(num.getNswStr()));
//
//        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(6);
//        values[6] = new KnownSymbolicValue(attribute.find(num.gettknAf1()));
//
//        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(7);
//        values[7] = new KnownSymbolicValue(attribute.find(num.gettknAf2()));
//        Item item = new Item(values);
//        return item;


        AttributeValue[] values = new AttributeValue[6];


//        IdSymbolicAttribute attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(3);
//        values[3] = new KnownSymbolicValue(attribute.find(num.gettknBf2()));
//
//        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(4);
//        values[4] = new KnownSymbolicValue(attribute.find(num.gettknBf1()));

        IdSymbolicAttribute attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(1);
        int index = attribute.find(num.gettknBf2());
        if (index == -1) {
            values[1] = new UnknownSymbolicValue();
        } else {
            values[1] = new KnownSymbolicValue(index);
        }

        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(2);
        index = attribute.find(num.gettknBf1());
        if (index == -1) {
            values[2] = new UnknownSymbolicValue();
        } else {
            values[2] = new KnownSymbolicValue(index);
        }

        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(3);
        index = attribute.find(num.getNswStr());
        if (index == -1) {
            values[3] = new UnknownSymbolicValue();
        } else {
            values[3] = new KnownSymbolicValue(index);
        }

        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(4);
        index = attribute.find(num.gettknAf1());
        if (index == -1) {
            values[4] = new UnknownSymbolicValue();
        } else {
            values[4] = new KnownSymbolicValue(index);
        }

        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(5);
        index = attribute.find(num.gettknAf2());
        if (index == -1) {
            values[5] = new UnknownSymbolicValue();
        } else {
            values[5] = new KnownSymbolicValue(index);
        }
//        attribute = (IdSymbolicAttribute) attributeSet.attributes().elementAt(7);
//        values[7] = new KnownSymbolicValue(attribute.find(num.gettknAf2()));
        Item item = new Item(values);
        return item;
    }

    public void setTokenAr(String inf) throws FileNotFoundException, XMLStreamException {
        FileInputStream fis = new FileInputStream(inf);
        XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(fis);
        ArrayList tokenAr = new ArrayList();
        while (xmlStreamReader.hasNext()) {
            int eventCode = xmlStreamReader.next();
            switch (eventCode) {
                case XMLStreamConstants.START_ELEMENT:
                    String localName = xmlStreamReader.getLocalName();
                    if (localName.equals("W")) {
                        String attributeValue = xmlStreamReader.getAttributeValue(0);
                        String nsw = xmlStreamReader.getElementText();
                        Token tkn = new Token();
                        tkn.setValue(nsw);
                        tkn.setNsw(attributeValue);
                        tokenAr.add(tkn);


                    }
                    break;
                case XMLStreamConstants.CHARACTERS:
                    String character = xmlStreamReader.getText();
                    StringTokenizer st = new StringTokenizer(character);
                    while (st.hasMoreTokens()) {

                        String tokenStr = st.nextToken();
                        Token token = new Token();
                        token.setValue(tokenStr);
                        token.setNsw("NOT");
                        tokenAr.add(token);
                    }

            }
        }


        this.tokenAr = tokenAr;

    }

    public void setItemAr() {

        for (int i = 0; i < this.tokenAr.size(); i++) {
            Token tkn = new Token();
            tkn = (Token) this.tokenAr.get(i);
            String tag = tkn.getNsw();
            String nswStr = tkn.getValue();
            if (isNgangCheo(nswStr)) {
                ALPHA item = new ALPHA();
                String tknValue = tkn.getValue();
                String tknNsw = tkn.getNsw();
                item.setclassNsw(tknNsw);

                //  nsw.setisNumSq(1);
                item.settknAf1(getToken(i + 1));
                item.settknAf2(getToken(i + 2));
                item.settknBf1(getToken(i - 1));
                item.settknBf2(getToken(i - 2));
                item.setNswStr(tknValue);
                itemAr.add(item);
            }

        }

    }

    public String getToken(int index) {
        if (index < 0 || index >= this.tokenAr.size()) {
            return "";
        } else {
            Token tkn = (Token) this.tokenAr.get(index);
            return tkn.getValue();
        }

    }

    public void asignFullValue(String inf, String ouf) throws XMLStreamException, UnsupportedEncodingException, IOException {
        FileInputStream fis = new FileInputStream(inf);
        XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(fis);

        FileOutputStream fos = new FileOutputStream(ouf);
        OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
        XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(osw);
        int index = 0;
        xmlStreamWriter.writeStartElement("root");
        while (xmlStreamReader.hasNext()) {
            int eventCode = xmlStreamReader.next();
            switch (eventCode) {

                case XMLStreamConstants.START_ELEMENT:
                    String localName = xmlStreamReader.getLocalName();
                    if (localName.equals("record")) {
                        String RecId = xmlStreamReader.getAttributeValue(0);
                        xmlStreamWriter.writeStartElement(localName);
                        xmlStreamWriter.writeAttribute("RecId", RecId);

                    }

                    if (localName.equals("URL")) {
                        String url = xmlStreamReader.getElementText();

                        xmlStreamWriter.writeStartElement(localName);
                        xmlStreamWriter.writeCharacters(url);
                        xmlStreamWriter.writeEndElement();

                    }
                    if (localName.equals("Infomation")) {
                        xmlStreamWriter.writeStartElement(localName);
                    }
                    if (localName.equals("W")) {
                        String attributeName = xmlStreamReader.getAttributeLocalName(0);
                        String attributeValue = xmlStreamReader.getAttributeValue(0);
                        if (attributeValue.equals("PUNC")) {
                            String nsw = xmlStreamReader.getElementText();
                            if (isNgangCheo(nsw)) {

                                String full = guessFull(index);
                                index++;
                                xmlStreamWriter.writeStartElement(localName);
                                xmlStreamWriter.writeAttribute("NSW", "PUNC");
                                xmlStreamWriter.writeAttribute("FULL", full);
                                xmlStreamWriter.writeCharacters(nsw);
                                xmlStreamWriter.writeEndElement();

                            } else {
                                xmlStreamWriter.writeStartElement(localName);
                                xmlStreamWriter.writeAttribute(attributeName, attributeValue);
                                xmlStreamWriter.writeCharacters(nsw);
                                xmlStreamWriter.writeEndElement();
                            }
                        } else {
                            if (attributeValue.equals("EXPN")) {
                                String fullValue = xmlStreamReader.getAttributeValue(1);
                                String nsw = xmlStreamReader.getElementText();
                                xmlStreamWriter.writeStartElement(localName);
                                xmlStreamWriter.writeAttribute(attributeName, attributeValue);
                                xmlStreamWriter.writeAttribute("FULL", fullValue);
                                xmlStreamWriter.writeCharacters(nsw);
                                xmlStreamWriter.writeEndElement();
                            } else {
                                String nsw = xmlStreamReader.getElementText();
                                xmlStreamWriter.writeStartElement(localName);
                                xmlStreamWriter.writeAttribute(attributeName, attributeValue);
                                xmlStreamWriter.writeCharacters(nsw);
                                xmlStreamWriter.writeEndElement();
                            }
                        }

                    }

                    if (localName.equals("SPLIT")) {
                        xmlStreamWriter.writeStartElement(localName);
                    }
                    break;

                case XMLStreamConstants.END_ELEMENT:
                    String endLocalName = xmlStreamReader.getLocalName();

                    if (endLocalName.equals("record")) {
                        xmlStreamWriter.writeEndElement();
                    }
                    if (endLocalName.equals("Infomation")) {
                        xmlStreamWriter.writeEndElement();
                    }

                    if (endLocalName.equals("SPLIT")) {
                        xmlStreamWriter.writeEndElement();
                    }
                    break;
                case XMLStreamConstants.CHARACTERS:
                    String character = xmlStreamReader.getText();
                    xmlStreamWriter.writeCharacters(character);
                    break;

                default:
                    break;
            }
        }

        xmlStreamWriter.writeEndElement();

        xmlStreamReader.close();
        xmlStreamWriter.close();
        fis.close();
        fos.close();

    }

    public void setGreek() throws UnsupportedEncodingException, FileNotFoundException, IOException {
//        greekAr.add("I");
//        greekAr.add("II");
//        greekAr.add("III");
//        greekAr.add("IV");
//        greekAr.add("V");
//        greekAr.add("VI");
//        greekAr.add("VII");
//        greekAr.add("VIII");
//        greekAr.add("IX");
//        greekAr.add("X");
//        greekAr.add("XI");
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("resources\\greekNumber.db"), "UTF8"));
        String greekNumber;
        int i = 0;
        while ((greekNumber = br.readLine()) != null) {
            greekAr.add(greekNumber);
//            i++;
        }
    }

    public boolean isWord(String nsw) {
        if (wordAr.contains(nsw)) {
            return true;
        }
//        if(nsw.equals("'")){
//            return true;
//        }
        return false;
    }

    public boolean isNgangCheo(String nsw) {
        Pattern p = Pattern.compile("[\\p{Pd}/]");
        Matcher m = p.matcher(nsw);
        return m.find();

    }
}
